home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1998 March
/
Macworld (1998-03) (Disk 1).dmg
/
Shareware World
/
Info
/
For Developers
/
GhostScript 5.10
/
MacGS-510
/
files
/
t1tot2.ps
< prev
next >
Wrap
Text File
|
1997-09-20
|
13KB
|
486 lines
% Copyright (C) 1997 Aladdin Enterprises. All rights reserved.
%
% This file is part of Aladdin Ghostscript.
%
% Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
% or distributor accepts any responsibility for the consequences of using it,
% or for whether it serves any particular purpose or works at all, unless he
% or she says so in writing. Refer to the Aladdin Ghostscript Free Public
% License (the "License") for full details.
%
% Every copy of Aladdin Ghostscript must include a copy of the License,
% normally in a plain ASCII text file named PUBLIC. The License grants you
% the right to copy, modify and redistribute Aladdin Ghostscript, but only
% under certain conditions described in the License. Among other things, the
% License requires that the copyright notice and this notice be preserved on
% all copies.
% t1tot2.ps
% Convert a Type 1 font with Type 1 CharStrings to Type 2.
% **************** THIS FILE DOES NOT WORK. ****************
% **************** DON'T TRY TO USE IT. ****************
(type1ops.ps) runlibfile
% ---------------- CharString conversion ---------------- %
% In the following lists, implemented conversions are marked with a +.
% The following conversions are required for each CharString:
% + Remove lenIV initial bytes and decrypt.
% + Move width to first stem/moveto.
% + Move all hstem/vstem commands to the beginning,
% including any from subroutines.
% Fold side bearing into first moveto.
% + Adjust Subr indices for bias.
% + Remove all closepath.
% Convert Flex othersubrs to new flex commands.
% Convert hint replacement to -hm and hintmask.
% Convert MM blend othersubrs to new blend command.
% For seac, convert char bodies to subrs, add hint replacement.
% + Make width relative to nominalWidthX, or omit if equal to
% defaultWidthX.
% The following patterns allow shortening CharStrings:
% + rlineto+ => rlineto
% + rlineto+ (hlineto | vlineto) rlineto+ => rlineto
% + vlineto (hlineto vlineto)* [hlineto] => vlineto
% + hlineto (vlineto hlineto)* [vlineto] => hlineto
% + rrcurveto+ => rrcurveto
% + rrcurveto+ rlineto => rcurveline
% + rlineto+ rrcurveto => rlinecurve
% + (vhcurveto hvcurveto)* [vhcurveto ["hrcurveto"] | "vrcurveto"] =>
% vhcurveto
% + (hvcurveto vhcurveto)* [hvcurveto ["vrcurveto"] | "hrcurveto"] =>
% hvcurveto
% "rvcurveto" (0 y1 x2 y2 0 y3 rrcurveto)* => vvcurveto
% "hrcurveto" (x1 0 x2 y2 x3 0 rrcurveto)* => hhcurveto
% Convert a CharString from Type 1 to Type 2.
% Free variables: font, subrmap.
/t1tot2cs { % <charstring1> <forsubr> t1tot2cs <charstring2>
10 dict begin
/forsubr exch def
% Collect the hints, side bearing, and width.
/vhints 10 dict def
/hhints 10 dict def
/hmcount null def
/lsb null def
/width null def
forsubr not {
dup t1hintops t1scan pop
} if
t1t2ops t1scan
[
forsubr not {
% Insert the hints and width at the beginning.
width dup font /nominalWidthX .knownget { sub } if
exch font /defaultWidthX .knownget not { 0 } if
eq { pop } if
/hstem hhints hintlist
/vstem vhints hintlist
} if
counttomark 2 add -1 roll aload pop ]
% Convert the string back to encoded form.
DEBUG {
(++++ ) print [ 1 index { dup null eq { pop } if } forall ] == flush
} if
/lenIV 0 def % for charproc_string
charproc_string end
} bind def
/hintlist { % <hintop> <dict> hintlist -
dup length 0 eq {
pop pop
} {
dup length array dup 3 -1 roll {
exch put dup
} forall pop
% ****** SORT THE HINTS BY INCREASING v ******
{ dup length 24 le { exit } if
dup 0 24 getinterval { aload pop 4 2 roll } forall
dup length 24 sub 24 exch getinterval
} loop
{ aload pop 3 2 roll } forall
} ifelse
} bind def
/uneexec { % <string> <lenIV> uneexec <string>
dup 0 ge {
2 copy mark /seed 4330 /lenIV 5 -1 roll .dicttomark /eexecDecode filter
% Stack: string lenIV filter
dup 4 -1 roll length 4 -1 roll sub string readstring pop
exch closefile
} {
pop
} ifelse
} bind def
/t1scan { % <charstring> <opsdict> t1scan <tokens>
5 dict begin
/opsdict exch def
% Remove encryption and convert to symbolic form for processing.
font /lenIV .knownget not { 4 } if uneexec
0 () /SubFileDecode filter /f exch def
/cstr [ 20 { null } repeat f charstack_read /END 20 { null } repeat ] def
DEBUG {
(**** ) print [ cstr { dup null eq { pop } if } forall ] == flush
} if
% Scan the unpacked string.
/i 20 def {
% The /END token will exit from this loop.
opsdict cstr i get .knownget { exec } if
/i i 1 add def
} loop
f closefile cstr end
} bind def
/ciget { % <di> ciget <token>
i add cstr exch get
} bind def
/ciput { % <di> <token> ciput -
exch i add exch cstr 3 1 roll put
} bind def
/ciswap { % <di> <dj> ciswap -
2 copy exch ciget exch ciget 3 1 roll ciput ciput
} bind def
/ciskip { % <di> ciskip -
i add /i exch def
} bind def
% Hint scanning procedures.
/addhint { % [<v> <dv>] <hintdict> addhint -
dup 2 index known { pop pop } { dup length 3 -1 roll exch put } ifelse
} bind def
/t1hintops mark /END { 0 null ciput exit } bind
/vstem {
cstr i 2 sub 2 getinterval vhints addhint
} bind
/hstem {
cstr i 2 sub 2 getinterval hhints addhint
} bind
/callsubr {
%**** DOESN'T HANDLE FLEX YET ****
-1 ciget /pop eq {
% This must be a <#> 1 3 /callothersubr /pop /callsubr sequence.
hmcount null eq { /hmcount [ vhints length hhints length ] store } if
-5 ciget
} {
-1 ciget
} ifelse
subrmap 1 index .knownget { exch pop } if
dup null eq { pop } {
font /Private get /Subrs get exch get
t1hintops t1scan pop
} ifelse
} bind
/hsbw {
/lsb -2 ciget store
/width -1 ciget store
} bind
/vstem3 {
[ -6 ciget -5 ciget ] vhints addhint
[ -4 ciget -3 ciget ] vhints addhint
[ -2 ciget -1 ciget ] vhints addhint
} bind
/hstem3 {
[ -6 ciget -5 ciget ] hhints addhint
[ -4 ciget -3 ciget ] hhints addhint
[ -2 ciget -1 ciget ] hhints addhint
} bind
/sbw {
%**** WHAT ABOUT Y? ****
/lsb -4 ciget store
/width -2 ciget store
} bind
.dicttomark readonly def % t1hintops
% Conversion procedures.
/t1t2ops mark /END { 0 null ciput exit } bind
/hstem {
% We handled the hints separately, drop them here.
-2 1 0 { null ciput } for
} bind
/vstem 1 index
/rlineto {
3 ciget /rlineto eq {
0 null ciput
} {
7 ciget /rrcurveto eq {
0 null ciput
7 /rlinecurve ciput
} {
5 ciget /rlineto eq {
2 ciget /hlineto eq {
0 null ciput
2 0 ciput
} {
2 ciget /vlineto eq {
0 0 ciput
2 null ciput
} if
} ifelse
} if
} ifelse
} ifelse
} bind
/vlineto {
2 ciget /hlineto eq {
0 null ciput
2 4 ciget /vlineto eq { null } { /vlineto } ifelse ciput
} if
} bind
/hlineto {
2 ciget /vlineto eq {
0 null ciput
2 4 ciget /hlineto eq { null } { /hlineto } ifelse ciput
} if
} bind
/rrcurveto {
7 ciget /rrcurveto eq {
0 null ciput
} {
3 ciget /rlineto eq {
0 null ciput
3 /rcurveline ciput
} {
%**** WRONG IF MULTIPLE RRCURVETO ****
-6 ciget 0 eq {
-6 null ciput
0 /vhcurveto ciput
} {
-5 ciget 0 eq {
-5 null ciput
-1 -2 ciswap
0 /hvcurveto ciput
} if
} ifelse
} ifelse
} ifelse
} bind
/callsubr {
-1 ciget subrmap 1 index .knownget { exch pop } if
% If the Subr was deleted because it was empty, delete the call.
dup null eq {
0 null ciput
} {
% Subtract the subroutineNumberBias.
107 sub
} ifelse -1 exch ciput
} bind
/vhcurveto {
5 ciget /hvcurveto eq {
0 null ciput
10 ciget /vhcurveto eq {
5 null ciput
} {
12 ciget /rrcurveto eq 6 ciget 0 eq and {
5 null ciput
6 null ciput
12 /vhcurveto ciput
12 ciskip
} {
5 /vhcurveto ciput
5 ciskip
} ifelse
} ifelse
} {
7 ciget /rrcurveto eq {
1 ciget 0 eq {
0 null ciput
1 null ciput
5 6 ciswap
7 /vhcurveto ciput
7 ciskip
} if
} if
} ifelse
} bind
/hvcurveto {
5 ciget /vhcurveto eq {
0 null ciput
10 ciget /hvcurveto eq {
5 null ciput
} {
12 ciget /rrcurveto eq 7 ciget 0 eq and {
5 null ciput
7 null ciput
10 11 ciswap
12 /hvcurveto ciput
12 ciskip
} {
5 /hvcurveto ciput
5 ciskip
} ifelse
} ifelse
} {
7 ciget /rrcurveto eq {
2 ciget 0 eq {
0 null ciput
2 null ciput
7 /hvcurveto ciput
7 ciskip
} if
} if
} ifelse
} bind
/closepath {
0 null ciput
} bind
/hsbw {
% We handled this separately, drop it.
-2 1 0 { null ciput } for
} bind
/dotsection {
%**************** NYI ****************
} bind
/vstem3 {
% We handled the hints separately, drop them here.
-6 1 0 { null ciput } for
} bind
/hstem3 1 index
/seac {
%**************** NYI ****************
} bind
/sbw {
% We handled this separately, drop it.
-4 1 0 { null ciput } for
} bind
/callothersubr {
-1 ciget 3 eq {
%**** HANDLE HINT REPLACEMENT ****
-2 ciget 1 eq 1 ciget /pop eq and 2 ciget /callsubr eq and {
1 -3 ciget ciput
-3 1 0 { null ciput } for
} {
(**************** 3 callothersubr -- invalid call\n) print
/t1tot2cs cvx /rangecheck signalerror
} ifelse
} if
} bind
/pop {
%**************** NYI ****************
} bind
/setcurrentpoint {
%**************** NYI ****************
} bind
.dicttomark readonly def % t1t2ops
% ---------------- Font conversion ---------------- %
% Copy a font, and remove eexec encryption from it.
/decryptfont { % <font> decryptfont <font'>
% Copy the font, CharStrings, Private, and Private.Subrs
dup length dict copy
dup /CharStrings 2 copy get dup length dict copy put
dup /Private 2 copy get dup length dict copy
dup /Subrs 2 copy get dup length array copy put
put
dup /lenIV .knownget not { 4 } if
1 index /CharStrings get
% Stack: font' lenIV chars'
dup { 3 index uneexec 2 index 3 1 roll put } forall pop
1 index /Private get /Subrs get
% Stack: font' lenIV Subrs'
0 1 2 index length 1 sub {
2 copy get dup type /stringtype eq {
% Stack: font' lenIV Subrs' index subr
3 index uneexec
} if 2 index 3 1 roll put
} for pop pop dup /lenIV -1 put
} def
% Convert an entire font from Type 1 to Type 2.
/t1tot2font { % <font> t1tot2font <font'>
10 dict begin
/font exch def
/niv font /lenIV .knownget not { 4 } if def
% Print initial statistics.
(lenIV = ) print niv =
font /CharStrings get
dup length =only ( CharStrings, ) print
0 exch { exch pop length add } forall =only ( bytes) =
font /Private get /Subrs get
dup length =only ( Subrs, ) print
0 exch { length add } forall =only ( bytes) =
flush
% Remove CharString encryption from the font.
/font font decryptfont def
/chars font /CharStrings get dup length dict copy def
/subrs font /Private get /Subrs get def
% Remove empty Subrs, including Subrs 0-3.
/subrmap subrs length dict def
0 1 3 { subrs exch <0b> put } for
0 1 subrs length 1 sub {
subrs 1 index get true t1tot2cs
length 1 eq {
subrs 1 index null put
subrmap exch null put
} {
pop
} ifelse
} for
% Remove duplicate Subrs (!).
% Make an entry in subrdict for each distinct Subr:
% key = Subr charstring, value = (lowest) Subr index.
% At the same time, make entries in subrmap for any duplicates:
% key = higher index, value = lowest index.
/subrdict subrs length dict def
0 0 1 subrs length 1 sub {
% Stack: toindex fromindex
subrs 1 index get subrdict 1 index .knownget {
% Stack: toindex fromindex subr firstindex
subrmap 4 -1 roll 3 -1 roll put pop
} {
dup null ne {
% Stack: toindex fromindex subr
subrmap 3 -1 roll 3 index put % fromindex => toindex
subrdict 1 index 3 index put % subr => toindex
subrs 2 index 3 -1 roll put % toindex => subr
1 add
} {
pop pop
} ifelse
} ifelse
} for
/subrs1 subrs 0 4 -1 roll getinterval def
font /Private get /Subrs subrs1 put
% Convert the font.
/chars2 chars length dict def
chars { false t1tot2cs chars2 3 1 roll put } forall
/subrs2 subrs1 length array def
0 1 subrs1 length 1 sub {
subrs1 1 index get true t1tot2cs
subrs2 3 1 roll put
} for
font /Private get /Subrs subrs2 put
% Print final statistics.
(CharStrings => ) print 0 chars2 { exch pop length add } forall =only
( bytes) =
subrs2 length =only ( Subrs, ) print
0 subrs2 { length add } forall =only ( bytes) =
flush
% Clean up the font.
font /lenIV undef
font /UniqueID undef
font /FID undef
font /CharStrings chars2 put
font /CharstringType 2 put
font end
} bind def